{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Testing Individual components of the FV HE scheme"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import random\n",
    "\n",
    "from syft.frameworks.torch.he.fv.modulus import CoeffModulus\n",
    "from syft.frameworks.torch.he.fv.encryption_params import EncryptionParams\n",
    "from syft.frameworks.torch.he.fv.context import Context\n",
    "from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder\n",
    "from syft.frameworks.torch.he.fv.key_generator import KeyGenerator\n",
    "from syft.frameworks.torch.he.fv.encryptor import Encryptor\n",
    "from syft.frameworks.torch.he.fv.decryptor import Decryptor\n",
    "from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder\n",
    "from syft.frameworks.torch.he.fv.modulus import SeqLevelType\n",
    "from syft.frameworks.torch.he.fv.evaluator import Evaluator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Keygeneration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "poly_modulus = 64\n",
    "bit_sizes= [40]\n",
    "plain_modulus = 64\n",
    "ctx = Context(EncryptionParams(poly_modulus, CoeffModulus().create(poly_modulus, bit_sizes), plain_modulus))\n",
    "keygenerator = KeyGenerator(ctx)\n",
    "sk, pk = keygenerator.keygen()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "[1099511623297]\n"
    }
   ],
   "source": [
    "print(ctx.param.coeff_modulus)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "secret key values :  [[0, 1099511623296, 1, 1, 1099511623296, 1, 0, 1099511623296, 1, 1099511623296, 1099511623296, 1099511623296, 1099511623296, 1099511623296, 0, 0, 1, 1099511623296, 0, 0, 0, 1099511623296, 1, 1099511623296, 1, 1, 1, 0, 1099511623296, 1099511623296, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1099511623296, 1099511623296, 1, 1, 1, 1, 1099511623296, 1099511623296, 0, 0, 1099511623296, 1, 1, 0, 1, 1099511623296, 1, 0, 1, 1099511623296, 0, 0, 1099511623296, 0, 1099511623296]]\n"
    }
   ],
   "source": [
    "# print(len(sk.data))\n",
    "print('secret key values : ', sk.data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(pk.data)\n",
    "# print('public key values : ', pk.data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Integer Encoder\n",
    "Encodes Integer values to Plaintext object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "[0, 1]     [0, 1, 0, 1]     [0, 0, 1]\n"
    }
   ],
   "source": [
    "int_encoder = IntegerEncoder(ctx)\n",
    "ri1 = random.randint(0,10)\n",
    "ri2 = random.randint(0,10)\n",
    "ri3 = random.randint(0,10)\n",
    "pt1 = int_encoder.encode(ri1)\n",
    "pt2 = int_encoder.encode(ri2)\n",
    "pt3 = int_encoder.encode(ri3)\n",
    "print(pt1.data,\"   \", pt2.data, \"   \", pt3.data)\n",
    "# print('plaintext data',plaintext.data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Decodes back to Integer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "2\n10\n4\n"
    }
   ],
   "source": [
    "print(int_encoder.decode(pt1))\n",
    "print(int_encoder.decode(pt2))\n",
    "print(int_encoder.decode(pt3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Encrypter\n",
    "Encrypt Plaintext to ciphertext using public_key"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "encrypter = Encryptor(ctx, pk)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "ct1 = encrypter.encrypt(pt1)\n",
    "ct2 = encrypter.encrypt(pt2)\n",
    "ct3 = encrypter.encrypt(pt3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Encrypt Plaintext to ciphertext using secret_key"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Decryptor\n",
    "Decrypt Ciphertext to Plaintext using secret_key"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "decrypter = Decryptor(ctx, sk)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "dec1 = decrypter.decrypt(ct1)\n",
    "dec2 = decrypter.decrypt(ct2)\n",
    "dec3 = decrypter.decrypt(ct3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "2     10     4\n"
    }
   ],
   "source": [
    "print(int_encoder.decode(dec1), \"   \", int_encoder.decode(dec2), \"   \", int_encoder.decode(dec3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "eval = Evaluator(ctx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "12\n"
    }
   ],
   "source": [
    "cc12 = eval.add(ct1, ct2)\n",
    "cc12 = decrypter.decrypt(cc12)\n",
    "print(int_encoder.decode(cc12))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "12\n"
    }
   ],
   "source": [
    "pc12 = eval.add(pt1, ct2)\n",
    "pc12 = decrypter.decrypt(pc12)\n",
    "print(int_encoder.decode(pc12))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "12\n"
    }
   ],
   "source": [
    "pp12 = eval.add(pt1, pt2)\n",
    "print(int_encoder.decode(pp12))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Verify result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert int_encoder.decode(cc12) == int_encoder.decode(pc12) == int_encoder.decode(pp12) == ri1+ri2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "\n\nct1 : [[[1042665945075, 916558144260, 1044174421481, 210629152726, 847821787156, 534894345004, 763475050322, 1033922928488, 532772495248, 351443634171, 1093570136397, 1006841470961, 377936268283, 147046430775, 970183333355, 847329897793, 667471202702, 176662347509, 919648546066, 796441831579, 275081728359, 407687223886, 344513077501, 899118994863, 860389120643, 467753443738, 119725953496, 894760788805, 851090554632, 823548090674, 351534884471, 50687760242, 595463970022, 434506787772, 586276619829, 337725279644, 735579946766, 511011770164, 450013503941, 542766713743, 311432052482, 979771104334, 194974774539, 760908664549, 229372331842, 437253620955, 435574411594, 937959646039, 982777761329, 770521129800, 6214731693, 76094852900, 131833917135, 649660765117, 1200241420, 428350364244, 920846207780, 192005048959, 603237170, 574887659510, 310476840958, 316729173050, 720651025894, 57302224595]], [[787708916333, 612305453753, 503055916075, 265330060304, 967037136757, 1084209027336, 852537584879, 596009293454, 545315984284, 89629478514, 500310893722, 913635272488, 295331741414, 343170521360, 440884132924, 581218043564, 33460522930, 74158105179, 323823980986, 146114471480, 676087278909, 243911193038, 413021988266, 955351839796, 840461138011, 961133130920, 528311773385, 265522350713, 321109105178, 206248972455, 174064935921, 1050332569006, 260899814482, 545123058910, 843199852499, 777269994295, 927317252133, 817358300955, 644149364338, 262915863359, 864407703940, 315167079979, 239198950163, 100585200786, 602519089033, 763797387073, 114190291157, 859475750349, 599593877147, 172868742508, 430120457778, 948660869026, 721632921867, 373424760414, 92045226725, 439108553694, 584669091328, 631410978903, 479865998565, 41996167970, 504676203801, 437975668245, 41317672422, 282897743591]]]\n\n\nct2 : [[[536821766082, 585811519751, 713117807512, 453910120189, 969782634823, 293602305066, 370327689694, 837251947672, 169966145043, 159057006308, 82219478630, 286841273088, 961884851812, 3524731701, 797779128802, 54029609253, 534388427994, 1035671716795, 971032879986, 760615459955, 1755712634, 171301454914, 855481318547, 651222568531, 591671179453, 880891842782, 694051268864, 242920355771, 315336614397, 355443273823, 145024819419, 384022590009, 465400970283, 132693141744, 81818035682, 215064320534, 145249611055, 84790849906, 360503870492, 689102571563, 349174364279, 904676445732, 672964706925, 82994202862, 728243985058, 747888667666, 673653640163, 109076520616, 420053159630, 807540689048, 708044469947, 717614098683, 528977486448, 948673843337, 6079372932, 485253989853, 455715362950, 814740225456, 370859807274, 643568687552, 955701725154, 291551477531, 718813946401, 588437535526]], [[533010224687, 545383495441, 567709192381, 108165556120, 516900927372, 826625739072, 448875783417, 1010286501280, 1094291450416, 136336175112, 970283543233, 352556949223, 184667360906, 572879480837, 699238808805, 844649364977, 863359915496, 502254584510, 524456402942, 75401951875, 858542782966, 219260635339, 2349901207, 695534318514, 1098827426359, 696786848670, 828761711538, 755624847980, 719268865331, 889182616769, 528286361623, 1005874934372, 301866186353, 938306569271, 544536703895, 157408270177, 722598784808, 905145409821, 990123723941, 1021179204412, 597535556990, 733745366742, 302706460432, 372047210407, 42526756666, 246250422418, 904656658054, 697399941349, 306536731809, 1008246605183, 440125592694, 308403793977, 738710884420, 215660228580, 292162081725, 468929778278, 676106983643, 704007234379, 634889958724, 252886483649, 320637080231, 683654774225, 1069805043714, 519601686952]]]\n\n\n\nfinal result:  20\n"
    }
   ],
   "source": [
    "result = eval._mul_cipher_cipher(ct1, ct2)\n",
    "print(\"\\n\\nct1 :\",ct1.data)\n",
    "print(\"\\n\\nct2 :\",ct2.data)\n",
    "print('\\n\\n')\n",
    "\n",
    "result = decrypter.decrypt(result)\n",
    "result = int_encoder.decode(result)\n",
    "\n",
    "print('final result: ', result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": "20      20\n"
    }
   ],
   "source": [
    "print(ri1 * ri2, \"    \", result)\n",
    "assert ri1 * ri2 == result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "file_extension": ".py",
  "kernelspec": {
   "display_name": "Python 3.7.7 64-bit",
   "language": "python",
   "name": "python37764bit7e2fa8fe9ae747e1a294a521efbce80f"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7-final"
  },
  "mimetype": "text/x-python",
  "name": "python",
  "npconvert_exporter": "python",
  "pygments_lexer": "ipython3",
  "version": 3
 },
 "nbformat": 4,
 "nbformat_minor": 2
}